package main

import (
	"context"
	"log"
	"net"
	"time"

	"navidb-node/config"
	"navidb-node/global"
	"navidb-node/logger"
	pb "navidb-node/proto"
	"navidb-node/rocksdb"

	"google.golang.org/grpc"
)

type NavidbServer struct {
	pb.UnimplementedNavidbServiceServer
}

func NewNavidbServer() *NavidbServer {
	return &NavidbServer{}
}

func (s *NavidbServer) Set(ctx context.Context, req *pb.SetDataReq) (*pb.SetDataResp, error) {
	err := global.RocksDBService.Write([]byte(req.Key), []byte(req.Value))
	if err != nil {
		return nil, err
	}
	return &pb.SetDataResp{Result: "ok"}, nil
}

func (s *NavidbServer) Get(ctx context.Context, req *pb.GetDataReq) (*pb.GetDataResp, error) {
	value, err := global.RocksDBService.Query([]byte(req.Key))
	if err != nil {
		return nil, err
	}
	return &pb.GetDataResp{Value: value}, nil
}

func (s *NavidbServer) Delete(ctx context.Context, req *pb.DeleteDataReq) (*pb.DeleteDataResp, error) {
	err := global.RocksDBService.Delete([]byte(req.Key))
	if err != nil {
		return nil, err
	}
	return &pb.DeleteDataResp{Result: "ok"}, nil
}

func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
	start := time.Now()
	// 调用前的处理
	// logger.Infof("Unary RPC: %s", info.FullMethod)
	// 执行RPC调用
	resp, err := handler(ctx, req)
	// 调用后的处理
	duration := time.Since(start)
	logger.Infof("Unary RPC %s completed in %v", info.FullMethod, duration)
	return resp, err
}

func main() {
	config.Init()
	logger.Init()
	go initRocksDB()

	logger.Infof(">>> Starting [%s] on port %s", config.Conf.App.AppName, config.Conf.App.Port)
	lis, err := net.Listen("tcp", ":"+config.Conf.App.Port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	s := grpc.NewServer(
	// grpc.UnaryInterceptor(unaryInterceptor),
	)
	pb.RegisterNavidbServiceServer(s, NewNavidbServer())

	logger.Infof("<<< server [%s] listening at %v", config.Conf.App.AppName, lis.Addr())
	if err := s.Serve(lis); err != nil {
		logger.Panic("failed to serve: %v", err)
	}
}

func initRocksDB() {
	logger.Infof(">>> Initializing RocksDB")
	var err error
	global.RocksDBService, err = rocksdb.NewRocksDBService(
		config.Conf.Rocks.NumShards,
		config.Conf.Rocks.DbPath,
	)
	if err != nil {
		logger.Errorf("Error initializing RocksDB : %v", err)
		logger.Panic(err)
	}
	logger.Info("<<< RocksDB initialized")
}
